home *** CD-ROM | disk | FTP | other *** search
- ;
- ; MTXCODE.ASM
- ;
- ; (Simon Hern, August 1993 - June 1995)
- ;
- ; Graphics routines for Matrix demo
- ; Three simple functions and the main animation routine
- ;
- ; (Some 32-bit code wouldn't go amiss here, but the assembler doesn't like
- ; that sort of thing, so too bad)
- ; (I'm sure there was some self-altering code in here somewhere last time
- ; I looked, but it seems to have been replaced. Pity. I miss it.)
- ;
-
-
- public _ScreenOn, _ScreenOff, _SetPalette
- public _DisplayMatrix
-
-
-
- ANGLES EQU 1024
- SCR_HEIGHT EQU 200
- SCR_WIDTH EQU 320
- VIEW_DIST EQU 512
- TILE_SIZE EQU 256*256
-
-
-
-
- _Text SEGMENT BYTE PUBLIC 'Code'
-
-
- VSYNC MACRO ; Macro waiting for vertical sync
- push dx
- push ax
- mov dx,03dah
- M1:
- in al,dx
- test al,8
- jnz M1
- M2:
- in al,dx
- test al,8
- jz M2
- pop ax
- pop dx
- #EM
-
-
-
- _ScreenOn: ; SCREENON(): vga, mode 13h, 320*200*256
- mov ax,00013h
- int 10h
- ret
-
-
-
- _ScreenOff: ; SCREENOFF(): text mode, 80*25 colour
- mov ax,00003h
- int 10h
- ret
-
-
-
- _SetPalette: ; SETPALETTE(char near *, int first, int number)
- push bp ; Table takes form of r-byte, g-byte, b-byte
- mov bp,sp ; repeated 'number' times
- push si
-
- mov si,w[bp+4] ; ds:si = start of colour table
- mov ax,w[bp+6] ; al = first colour to change
- mov cx,w[bp+8] ; cx = number of colours to change
- mov bx,cx
- shl cx,1
- add cx,bx
-
- VSYNC
- mov dx,03c8h
- out dx,al ; first colour
- inc dx
- spa01:
- lodsb
- out dx,al
- loop spa01
-
- pop si
- pop bp
- ret
-
-
-
- ; DisplayMatrix routine starts HERE
-
-
- UNROLL1 MACRO ; Unrolled central loop - start at middle, work right
- #RX1(SCR_WIDTH/4) ; i.e. Repeat SCR_WIDTH/4 times
- mov bl,ch
- mov bh,dh
- or al,b[bx] ; (bh,bl) = position within Tile array
- add cx,si
- add dx,bp ; Displace position (dx,cx) by (bp,si)
-
- mov bl,ch
- mov bh,dh
- or ah,b[bx] ; Same thing again
- add cx,si
- add dx,bp
-
- stosw ; Write two pixels at a time
- and ax,0E0E0h ; Clear ax except for 'blur' bits
- #ER
- #EM
-
-
- UNROLL2 MACRO ; Unrolled central loop 2 - start at middle, work left
- #RX1(SCR_WIDTH/4) ; i.e. Repeat SCR_WIDTH/4 times
- sub cx,si
- sub dx,bp ; Displace position (dx,cx) by (-bp,-si)
- mov bl,ch
- mov bh,dh
- or ah,b[bx] ; (bh,bl) = position within Tile array
-
- sub cx,si
- sub dx,bp
- mov bl,ch ; Same thing again
- mov bh,dh
- or al,b[bx]
-
- stosw ; Write two pixels at a time
- and ax,0E0E0h ; Clear ax except for 'blur' bits
- #ER
- #EM
-
-
-
- EVEN
-
- dmCosAngle: dw ? ; cos(angle) (16-bit fraction)
- dmSinAngle: dw ? ; sin(angle) (16-bit fraction)
-
- dmXPos: db ? ; Origin's x coordinate within a tile
- dmYPos: db ? ; Origin's y coordinate within a tile
-
- dmDistPtr: dw ? ; Pointer to place in Distances array
- dmBlursPtr: dw ? ; Pointer to place in Blurs array
- dmTilesSeg: dw ? ; Segment containing Tiles array (fills whole segment)
-
- dmLineCounter: db ? ; Keep track of number of lines to draw
-
-
- EVEN
-
- _DisplayMatrix: ; DisplayMatrix(int angle, int xpos, int ypos)
-
- push bp
- mov bp,sp
-
- push di
- push si
- push ds
- push es
-
- mov bx,w[bp+4] ; int angle
- shl bx,1
- mov ax,w[bx+OFFSET _AngleSines]
- mov cs:w[dmSinAngle],ax
- add bx,2*ANGLES/4
- and bx,2*ANGLES - 1
- mov ax,w[bx+OFFSET _AngleSines]
- mov cs:w[dmCosAngle],ax
-
- mov ax,w[bp+6] ; int xpos
- mov cs:b[dmXPos],al
-
- mov ax,w[bp+8] ; int ypos
- mov cs:b[dmYPos],al
-
- les di,d[_ScrBuffer] ; Draw image in buffer then copy to screen
- add di,SCR_WIDTH/2 ; es:di = buffer pointer
-
- mov ax,w[_Distances] ; Set up local copies of pointers
- mov cs:w[dmDistPtr],ax
- mov ax,w[_Blurs]
- mov cs:w[dmBlursPtr],ax
- mov ax,w[_Tile+2]
- mov cs:w[dmTilesSeg],ax
-
- mov cs:w[dmLineCounter],SCR_HEIGHT/2
-
- dm01: ; Draw each line
-
- mov bx,cs:w[dmDistPtr]
- add cs:w[dmDistPtr],2 ; Look up distance to line in array
- mov bx,w[bx] ; Then rotate distance through Angle
- mov ax,bx ; to get starting position on tile plane
- imul cs:w[dmCosAngle]
- mov cx,dx
- mov ax,bx
- imul cs:w[dmSinAngle] ; (cx,dx) = positn of middle point on line
-
- mov si,dx
- mov bp,cx
- neg bp ; (si,bp) = displacement to next point
-
- mov ch,cl ; Scale (cx,dx) up by factor of 256
- mov dh,dl ; so bottom 8 bits are 'fractional' part
- mov cl,0 ; Position is relative to one tile - all
- mov dl,0 ; tiles are identical
- add ch,cs:w[dmXPos]
- add dh,cs:w[dmYPos] ; Displace starting point by (XPos,YPos)
-
- mov bx,cs:w[dmBlursPtr] ; al = ah = blur bits for this line
- inc cs:w[dmBlursPtr] ; (It would be good if the blur bits could
- mov ah,b[bx] ; be 'stuck' onto the screen so that they
- mov al,ah ; don't have to be rewritten each frame,
- ; and also so that they could be arranged
- ; in a more random fading pattern than
- ; 'bands' of lines. This is probably
- ; possible by tweaking VGA registers but
- ; I don't know how to do it.)
-
- push ds
- mov ds,cs:w[dmTilesSeg]
-
- push cx
- push dx
- cld
-
- UNROLL1 ; Draw pixels to the left
-
- sub di,162
- pop dx
- pop cx
- std
-
- UNROLL2 ; Draw pixels to the right
-
- add di,162+320
-
- pop ds
-
- dec cs:b[dmLineCounter]
- jz dm02
- jmp dm01 ; Move on to next line
- dm02:
-
- cld
- lds si,d[_ScrBuffer]
- mov ax,0a000h
- mov es,ax
- mov di,SCR_WIDTH * SCR_HEIGHT / 2
- mov cx,SCR_WIDTH * (SCR_HEIGHT/2) / 2
- VSYNC
- rep movsw ; Spew buffer to screen on vsync
-
- pop es
- pop ds
- pop si
- pop di
-
- pop bp
- ret
-
-
- _TEXT ENDS
-
-